//
//  Ex+String.swift
//  ChinaPoem-Swift
//
//  Created by jh on 2022/12/14.
//

import UIKit
import Foundation

extension String {
    // 返回第一次出现的指定子字符串在此字符串中的索引
    //（如果backwards参数设置为true，则返回最后出现的位置）
    func positionOf(sub: String, backwards: Bool = false)->Int {
        var pos = -1
        if let range = range(of:sub, options: backwards ? .backwards : .literal) {
            if !range.isEmpty {
                pos = self.distance(from:startIndex, to:range.lowerBound)
            }
        }
        return pos
    }

    func encoding() -> String? {
        let data = self.data(using: .utf8)
        return data?.base64EncodedString()
    }
    
    func decoding() -> String? {
        if let data = Data(base64Encoded: self) {
            return String(data: data, encoding: .utf8)
        }
        return nil
    }
    
    var urlFormat: String {
        if let formatUrl = self.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
            if formatUrl.contains(".png") {
                return formatUrl.replacingOccurrences(of: ".png", with: ".webp")
            } else if formatUrl.contains(".jpg") {
                return formatUrl.replacingOccurrences(of: ".jpg", with: ".webp")
            } else {
                return formatUrl
            }
        } else {
            return self
        }
    }
    
    var tokenizer: [String] {
        let tokenize = CFStringTokenizerCreate(kCFAllocatorDefault, self as CFString?, CFRangeMake(0, self.count), kCFStringTokenizerUnitWord, CFLocaleCopyCurrent())
        CFStringTokenizerAdvanceToNextToken(tokenize)
        var range = CFStringTokenizerGetCurrentTokenRange(tokenize)
        var keyWords : [String] = []
        while range.length > 0 {
            let wRange = self.index(self.startIndex, offsetBy: range.location)..<self.index(self.startIndex, offsetBy: range.location + range.length)
            let keyWord = String(self[wRange])
            keyWords.append(keyWord)
            CFStringTokenizerAdvanceToNextToken(tokenize)
            range = CFStringTokenizerGetCurrentTokenRange(tokenize)
        }
        return keyWords
    }
    
    // 格式化手机号码
    func numberMask(format: String = "*** **** ****") -> String {
        let cleanNumber = components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
        
        var result = ""
        var startIndex = cleanNumber.startIndex
        let endIndex = cleanNumber.endIndex
        for char in format where startIndex < endIndex {
            if char == "*" {
                result.append(cleanNumber[startIndex])
                startIndex = cleanNumber.index(after: startIndex)
            } else {
                result.append(char)
            }
        }
        return result
    }
    
    // 范围替换
    func replaceRange(from: Int, to: Int, char: String = "*") -> String {
        var tempStr = self
        if from < 0 || from > to || to > tempStr.count { return tempStr }
        let start = tempStr.index(tempStr.startIndex, offsetBy: from)
        let end = tempStr.index(tempStr.startIndex, offsetBy: to)
        tempStr.replaceSubrange(start..<end, with: (from..<to).map { _ in char }.joined())
        return tempStr
    }
    
    
    
    // 计算文本高度
    func calculateTextHeight(font: UIFont, width: CGFloat) -> CGFloat {
        // 创建一个 NSAttributedString 属性字典
        let attributes: [NSAttributedString.Key: Any] = [.font: font]
        
        // 创建一个 NSAttributedString
        let attributedText = NSAttributedString(string: self, attributes: attributes)
        
        // 设置文本限制的宽度和无限高度
        let size = CGSize(width: width, height: .greatestFiniteMagnitude)
        
        // 计算文本高度
        let rect = attributedText.boundingRect(with: size, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
        
        // 返回高度，向上取整
        return ceil(rect.height)
    }
    
    // 计算文本高度
    var textHeight: CGFloat {
        let attributedString = NSMutableAttributedString(string: self)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 4
        paragraphStyle.paragraphSpacing = 8
        paragraphStyle.firstLineHeadIndent = 18
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 15, weight: .regular),
            .paragraphStyle: paragraphStyle
        ]
        
        attributedString.addAttributes(attributes, range: NSRange(location: 0, length: self.count))
        
        let textView = UITextView()
        textView.textContainerInset = .zero
        textView.attributedText = attributedString
        textView.isScrollEnabled = false
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.sizeToFit()
        
        let size = textView.sizeThatFits(CGSize(width: UIScreen.main.bounds.size.width - 70, height: CGFloat.greatestFiniteMagnitude))
        return size.height
    }
}

extension String {
    func trim(text: String) -> String {
        replacingOccurrences(of: text, with: "", options: .literal)
    }
}

// https://github.com/vincent-pradeilles/swift-tips#shorter-syntax-to-deal-with-optional-strings
extension Optional where Wrapped == String {
    var orEmpty: String {
        switch self {
        case let .some(value):
            return value
        case .none:
            return ""
        }
    }
}

extension String {
    func parseInt() -> Int? {
        // ref: https://stackoverflow.com/questions/30342744/swift-how-to-get-integer-from-string-and-convert-it-into-integer
        Int(components(separatedBy: CharacterSet.decimalDigits.inverted).joined())
    }
    
    // Mobile phone number verification
    var isMobile: Bool {
        // Just for test, in the real project uses the project verification rules
        return (self.hasPrefix("1") && self.replacingOccurrences(of: " ", with: "").count == 11)
    }
    
    // 📮Email Verification, simulation is set to true
    var isEmail: Bool {
        // Just for test, in the real project uses the project verification rules
        let predicate =  NSPredicate(format: "SELF MATCHES %@", "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$")
        return predicate.evaluate(with: self)
    }
}

// MARK: -- NSString -> String
extension String {
    var image: UIImage? {
        return UIImage(named: self)
    }
    
    var regularSysImage: UIImage? {
        return UIImage.systemImage(name: self, weight: .regular)
    }
    
    var mediumSysImage: UIImage? {
        return UIImage.systemImage(name: self, weight: .regular)
    }
    
    var thinImage: UIImage? {
        return UIImage.systemImage(name: self, weight: .thin)
    }
    
    var bundleImage: UIImage? {
        return UIImage(named: self, in: Bundle.resouseBundle, compatibleWith: nil)
    }
    
    var color: UIColor? {
        return UIColor(named: self)
    }
    
    var lastPath: String {
        return self.ns.lastPathComponent
    }
    
    var ns: NSString {
        return self as NSString
    }
    
    var pathExt: String {
        return self.ns.pathExtension
    }
    
    var deleteLastPath: String {
        return self.ns.deletingLastPathComponent
    }
    
    var deletePathExt: String {
        return self.ns.deletingPathExtension
    }
   
    func appendingPath(_ component: String) -> String {
        return self.ns.appendingPathComponent(component) as String
    }
    
    func appendingPathExt(_ ext: String) -> String? {
        return self.ns.appendingPathExtension(ext)
    }
    
    subscript(i: Int) -> String {
        let start = self.index(self.startIndex, offsetBy: i)
        let end = self.index(startIndex, offsetBy: 1)
        return String(self[start..<end])
    }
}
